package hc.bre.rest.admin

import static org.mockito.Mockito.RETURNS_DEFAULTS

import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.AuthenticationException
import org.apache.shiro.authc.IncorrectCredentialsException
import org.apache.shiro.authc.UsernamePasswordToken
import org.apache.shiro.subject.Subject
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.web.bind.annotation.RequestBody
import hc.bre.cmn.BreException
import hc.bre.project.ProjectDefinition
import hc.bre.rest.manage.MainService

@groovy.transform.CompileStatic
@Service
class BreAdminService {
	
	@Value('${rule.dir}')
	String ruledir
	
	@Autowired
	MainService mainService;
	
	String getFileName() {
		ruledir + '/application.config'
	}

	private BreAdminConfig cachedConfig;

	BreAdminConfig getConfig() {
		if(cachedConfig == null )
			cachedConfig =load();

		return cachedConfig;
	}

	BreAdminConfig load() {
		if(!hc.Util.fileExists(fileName)) {
			return BreAdminConfig.create();
		}

		Map map = hc.Util.jsonRead(hc.Util.fileReadText(fileName));

		return new BreAdminConfig().load(map);
	}


	BreAdminConfig save(Map map) {
		BreAdminConfig cfg = new BreAdminConfig().load(map)

		if(cfg.version  != config.version)
			throw new ObsoleteDataException();

		return save(cfg);
	}

	BreAdminConfig save(BreAdminConfig config) {
		config.version ++;
		hc.Util.jsonWriteToFile(config,fileName);
		cachedConfig = config;
		return config;
	}
	
	BreAdminConfig save() {
		save(config);
	}

	public BreUser login(String usercode,String userpwd,boolean rememberMe) {
		Subject subject = SecurityUtils.getSubject();
		subject.logout();

		BreUser user =  getUser(usercode,userpwd);
		if(user.forbidden) {
			throw new BreException("账户被停用。")
		}
		
		UsernamePasswordToken token = new UsernamePasswordToken(user.code,user.password);
		token.setRememberMe(rememberMe);
		subject.login(token);

		return user;
	}

	public void logout() {
		Subject subject = SecurityUtils.getSubject();
		subject.logout()
	}

	//current logining user or null
//	public BreUser user() {
//		Subject subject = SecurityUtils.getSubject();
//		BreUser usr = (BreUser) subject.getPrincipal();
//		return usr;
//	}

	private BreUser getUser(String usercode,String userpwd) {
		BreUser user = config.userList.find({it.code == usercode});
		if(!user) {
			throw new IncorrectCredentialsException();
		}

		String pwd  = AuthUtil.encriptPassword(userpwd, user.salt);
		if(user.password != pwd) {
			throw new IncorrectCredentialsException();
		}

		return user;
	}

	public BreUser changePwd(String usercode,String userpwd, String newpwd ) {
		boolean rememberMe = SecurityUtils.getSubject().isRemembered();
		logout();

		BreUser user =  getUser(usercode, userpwd);
		AuthUtil.updatePassword(user, newpwd);
		save(config);

		login(user.code,newpwd,rememberMe);

		return user;
	}


	Object resourceList() {
		List<ProjectEntry> projs = this.config.projectList
		
		List<LinkedHashMap> projList = projs.collect {
			Map m =  [
//				rid:it.rid,
				rname:it.rname,
				rpath:hc.Util.rpathPrjectCode(it.rpath) + '/' +'*',
				rtype:'project',//it.rtype,
				rpath2:it.rpath,
				list:[]] ;
			return m;
		}

		projList.each{ proj ->
			ProjectDefinition projDef = mainService.loadProject(proj.rpath2 as String);
			projDef.ruleList.each {  
				(proj.list as List).add([		
//					rid:it.rid,
					rname:it.rname,
					rpath:it.rpath,
					rtype:it.rtype,
				])
			}
		}

		return [
//			rid:-1,
			rname:'全部项目',
			rtype:'all',
			rpath:'*/*',
			list:projList,
		];
	}
}
